package ly.gupao.edu.java8.Strategy;

import java.io.File;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author: liyang
 * @date：2018/11/8 0008
 * describe：
 */
public class StrategyFactory {

    private static final String PACKAGE = "ly.gupao.edu.java8.Strategy";

    private ClassLoader classLoader = getClass().getClassLoader();

    private List<Class<? extends MyStrategy>> strategies;

    public StrategyFactory(){
        init();
    }

    public static StrategyFactory instance(){
        return new StrategyFactory();
    }

    public MyStrategy createStrategy(String str){
        for (Class<? extends MyStrategy> e : strategies) {
            StrategyRagion ragion = handleAnnotation(e);
            if(ragion.name().equalsIgnoreCase(str)){
                try {
                    return e.newInstance();
                } catch (InstantiationException e1) {
                    e1.printStackTrace();
                } catch (IllegalAccessException e1) {
                    e1.printStackTrace();
                }
            }
        }
        return null;
    }

    private StrategyRagion handleAnnotation(Class<? extends MyStrategy> clazz){
        Annotation[] annotations = clazz.getAnnotations();
        for (int i = 0; i < annotations.length; i++) {
            if (annotations[i] instanceof StrategyRagion) {
                return (StrategyRagion) annotations[i];
            }
        }
        return null;
    }

    private void init(){
        strategies = new ArrayList<>();
        File[] files = getFiles();
        Class<MyStrategy> strategyClazz = null;
        try {
            strategyClazz = (Class<MyStrategy>) classLoader.loadClass(MyStrategy.class.getName());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        Class<MyStrategy> finalStrategyClazz = strategyClazz;
        Arrays.stream(files).forEach(e -> {
            try {
                Class<?> clazz = classLoader.loadClass(PACKAGE + "." + e.getName().replace(".class", ""));
                if(MyStrategy.class.isAssignableFrom(clazz) && finalStrategyClazz != clazz){
                    strategies.add((Class<? extends MyStrategy>)clazz);
                }
            } catch (ClassNotFoundException e1) {
                e1.printStackTrace();
            }
        });
    }

    private File[] getFiles(){
        try {
            File files = new File(classLoader.getResource(PACKAGE.replace(".", "\\/")).toURI());
            return files.listFiles((e) -> e.getName().endsWith(".class"));
        }catch (Exception e){
            throw new RuntimeException("未找到策略资源");
        }
    }

}
